import React, { useRef, useImperativeHandle, useReducer } from 'react'

const ArrtsCom = (props) => {
  return (
    <div ref={props.myRef}>我是子组件</div>
  )
}

const ArrtsForward = React.forwardRef((props, ref) => {
  return (
    <div ref={ref}>我是forwardRef子组件</div>
  )
})

const ArrtsImperative = React.forwardRef(({}, ref) => {
  const inputRef = useRef();
  /**
   * 此时ref返回的内容就为useImperativeHandle定义的内容，则不会返回dom本身
   * 返回一个对象
   */
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus()
    },
    value: '我是自定义返回的value',
    dom: inputRef.current,  // 返回本身dom
  }))
  return (
    <div>
      <input ref={inputRef} type="text" placeholder='useImperativeHandle'/>
    </div>
  )
})


const Arrts: React.FC = () => {
  const resf = useRef(null)
  const refCom = useRef(null)
  const forWard = useRef(null)
  const imperative = useRef(null)

  /**
   * useReducer 
   * - useState的代替方案
   * - 它接收一个形如 (state, action) => newState 的 reducer，并返回当前的 state 以及与其配套的 dispatch 方法。
   */

  const count = 0
  const reducer = (state, action) => {
    // state 当前值
    // action为时间传递过来的值
    // 需要有return的值，否则再次点击获取的为undefined
    console.log(state, action)
    switch(action.type) {
      case 'add': return state + 1;
      case 'reduce': return state - 1;
      default: throw Error('没有相关操作')
    } 
  }

  const [state, dispatch] = useReducer(reducer, count)
  return (
    <div>
      arrt属性
      <div onClick={() => {
        console.log(forWard.current)
      }}>
        点击log ref信息
      </div>
      <div ref={resf} id="ids">我是展示的内容</div>
      {/* 此时给组件绑定ref则控制台提醒报错，输出的log信息为null, 绑定失败。 */}
      {/* 方法一：通过给组件传递参数，子组件进行绑定，这里通过对象存储的使用的时同一地址链接来保证ref绑定成功 */}
      <ArrtsCom myRef={refCom}/>
      {/* 方法二：通过react16新增加的方法React.forwardRef()来进行绑定 */}
      <ArrtsForward ref={forWard}/>


      useImperativeHandle hooks 子组件利用useImperativeHandle可以让父组件输出任意数据
      <br />
      <button onClick={() => {
        console.log(imperative)
        imperative.current.focus()
      }}>使用子组件的focus</button>
      <br />
      <ArrtsImperative ref={imperative}/>
      <h1>useReducer</h1>
      <h1>{state}</h1>
      <div>
        <button onClick={() => {
          dispatch({type: 'add'})
        }}>+1</button>
        <br />
        <button onClick={() => {
          dispatch({type: 'reduce'})
        }}>-1</button>
      </div>
    </div>
  )
}

export default Arrts


/**
 * 纯函数
 * - 相同的输入总是产生相同的结果，
 * - 无副作用
 */